// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: support for request discovery
// feature: content filter topic
// feature: Unified Transport Abstraction Layer Unified Transport Abstraction Layer
// feature: discovery support client and server
// feature: change idl check from md5 to crc16
// ------------------------------------------------------------------

#ifndef INCLUDE_EDDS_RTPS_BUILTIN_DATA_READERPROXYDATA_H_
#define INCLUDE_EDDS_RTPS_BUILTIN_DATA_READERPROXYDATA_H_
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

#include <ertps/attributes/TopicAttributes.h>
#include <ertps/qos/ReaderQos.h>
#include <history/RemoteEndpointInfo.h>
#include <edds/rtps/attributes/WriterAttributes.h>
#include <edds/rtps/attributes/RTPSParticipantAllocationAttributes.hpp>
#include <edds/rtps/common/RemoteLocators.hpp>
// #include <edds/dds/builtin/common/Types.hpp>
#if HAVE_SECURITY
#include <edds/rtps/security/common/AuthToken.h>
#include <edds/rtps/security/accesscontrol/EndpointSecurityAttributes.h>
#endif  // if HAVE_SECURITY

using namespace evbs::edds::dds;

namespace vbs {
namespace transport {
class TransportFactory;
}
}  // namespace vbs
namespace evbs {
namespace ertps {
namespace rtps {

struct CDRMessage_t;
class RTPSParticipantImpl;
/**
 * Class ReaderProxyData, used to represent all the information on a Reader (both local and remote)
 * with the purpose of implementing the discovery.
 * *@ingroup BUILTIN_MODULE
 */
class ReaderProxyData {
 public:
    RTPS_DllAPI ReaderProxyData(const size_t max_unicast_locators, const size_t max_multicast_locators);

    RTPS_DllAPI ReaderProxyData(const size_t max_unicast_locators, const size_t max_multicast_locators,
                                const VariableLengthDataLimits& data_limits);

    RTPS_DllAPI virtual ~ReaderProxyData();

    RTPS_DllAPI ReaderProxyData(const ReaderProxyData& readerInfo);

    RTPS_DllAPI ReaderProxyData& operator=(const ReaderProxyData& readerInfo);

    RTPS_DllAPI void guid(const GUID_t& guid) { m_guid = guid; }

    RTPS_DllAPI void guid(GUID_t&& guid) { m_guid = std::move(guid); }

    RTPS_DllAPI const GUID_t& guid() const { return m_guid; }

    RTPS_DllAPI GUID_t& guid() { return m_guid; }

    RTPS_DllAPI bool has_locators() const {
        return (!remote_locators_.unicast.empty()) || (!remote_locators_.multicast.empty());
    }

    RTPS_DllAPI void has_udp_dsf_locators(bool& take_udp_locator, uint32_t& queue_id);

    RTPS_DllAPI const RemoteLocatorList& remote_locators() const { return remote_locators_; }

    RTPS_DllAPI void set_remotelocators(const RemoteLocatorList& other_locators_) {
        remote_locators_ = other_locators_;
    }

    RTPS_DllAPI void add_unicast_locator(const Locator_t& locator);

    void set_announced_unicast_locators(const LocatorList_t& locators);

    RTPS_DllAPI void add_multicast_locator(const Locator_t& locator);

    void set_remote_unicast_locators(const LocatorList_t& locators, RTPSParticipantImpl* participant);

    void set_multicast_locators(const LocatorList_t& locators, RTPSParticipantImpl* participant);

    void set_locators(const RemoteLocatorList& locators);

    void set_remote_locators(const RemoteLocatorList& locators, RTPSParticipantImpl* participant,
                             bool use_multicast_locators);

    RTPS_DllAPI void key(const InstanceHandle_t& key) { m_key = key; }

    RTPS_DllAPI void key(InstanceHandle_t&& key) { m_key = std::move(key); }

    RTPS_DllAPI InstanceHandle_t key() const { return m_key; }

    RTPS_DllAPI InstanceHandle_t& key() { return m_key; }

    RTPS_DllAPI void RTPSParticipantKey(const InstanceHandle_t& RTPSParticipantKey) {
        m_RTPSParticipantKey = RTPSParticipantKey;
    }

    RTPS_DllAPI void RTPSParticipantKey(InstanceHandle_t&& RTPSParticipantKey) {
        m_RTPSParticipantKey = std::move(RTPSParticipantKey);
    }

    RTPS_DllAPI InstanceHandle_t RTPSParticipantKey() const { return m_RTPSParticipantKey; }

    RTPS_DllAPI InstanceHandle_t& RTPSParticipantKey() { return m_RTPSParticipantKey; }

    RTPS_DllAPI void typeName(const string_255& typeName) { m_typeName = typeName; }

    RTPS_DllAPI void typeName(string_255&& typeName) { m_typeName = std::move(typeName); }

    RTPS_DllAPI const string_255& typeName() const { return m_typeName; }

    RTPS_DllAPI string_255& typeName() { return m_typeName; }

    RTPS_DllAPI void topicName(const string_255& topicName) { m_topicName = topicName; }

    RTPS_DllAPI void topicName(string_255&& topicName) { m_topicName = std::move(topicName); }

    RTPS_DllAPI const string_255& topicName() const { return m_topicName; }

    RTPS_DllAPI string_255& topicName() { return m_topicName; }

    RTPS_DllAPI void userDefinedId(uint16_t userDefinedId) { m_userDefinedId = userDefinedId; }

    RTPS_DllAPI uint16_t userDefinedId() const { return m_userDefinedId; }

    RTPS_DllAPI uint16_t& userDefinedId() { return m_userDefinedId; }

    RTPS_DllAPI void isAlive(bool isAlive) { m_isAlive = isAlive; }

    RTPS_DllAPI bool isAlive() const { return m_isAlive; }

    RTPS_DllAPI bool& isAlive() { return m_isAlive; }

    RTPS_DllAPI void topicKind(TopicKind_t topicKind) { m_topicKind = topicKind; }

    RTPS_DllAPI TopicKind_t topicKind() const { return m_topicKind; }

    RTPS_DllAPI TopicKind_t& topicKind() { return m_topicKind; }

    void content_filter(const vbsutil::xmlparser::ContentFilterProperty& filter) { content_filter_ = filter; }

    void content_filter(vbsutil::xmlparser::ContentFilterProperty&& filter) { content_filter_ = std::move(filter); }

    const vbsutil::xmlparser::ContentFilterProperty& content_filter() const { return content_filter_; }

    vbsutil::xmlparser::ContentFilterProperty& content_filter() { return content_filter_; }

    inline bool disable_positive_acks() const { return m_qos.m_disablePositiveACKs.enabled; }

    /**
     * Set participant client server sample identity
     * @param sid valid SampleIdentity
     */
    void set_sample_identity(const SampleIdentity& sid) {
        edds::dds::set_proxy_property(sid, "PID_CLIENT_SERVER_KEY", m_properties);
    }

    /**
     * Retrieve participant SampleIdentity
     * @return SampleIdentity
     */
    SampleIdentity get_sample_identity() const {
        return edds::dds::get_proxy_property<SampleIdentity>("PID_CLIENT_SERVER_KEY", m_properties);
    }

    /**
     * Get the size in bytes of the CDR serialization of this object.
     * @param include_encapsulation Whether to include the size of the encapsulation info.
     * @return size in bytes of the CDR serialization.
     */
    uint32_t get_serialized_size(bool include_encapsulation) const;

    /**
     * Write as a parameter list on a CDRMessage_t
     * @return True on success
     */
    bool writeToCDRMessage(CDRMessage_t* msg, bool write_encapsulation) const;

    /**
     * Read the information from a CDRMessage_t. The position of the message must be in the
     * beginning on the parameter list.
     * @param msg Pointer to the message.
     * @param localParticipant Pointer to local participantimpl.
     * @return true on success
     */
    RTPS_DllAPI bool readFromCDRMessage(CDRMessage_t* msg_cdr, RTPSParticipantImpl* localParticipant);

    //! Reader Qos
    ReaderQos m_qos;

#if HAVE_SECURITY
    //! EndpointSecurityInfo.endpoint_security_attributes
    security::EndpointSecurityAttributesMask security_attributes_;

    //! EndpointSecurityInfo.plugin_endpoint_security_attributes
    security::PluginEndpointSecurityAttributesMask plugin_security_attributes_;

    security::AuthToken m_auth_token;
#endif  // if HAVE_SECURITY

    /**
     * Clear (put to default) the information.
     */
    void clear();

    /**
     * Check if this object can be updated with the information on another object.
     * @param rdata ReaderProxyData object to be checked.
     * @return true if this object can be updated with the information on rdata.
     */
    bool is_update_allowed(const ReaderProxyData& rdata) const;

    /**
     * Update the information (only certain fields will be updated).
     * @param rdata Pointer to the object from which we are going to update.
     */
    void update(ReaderProxyData* rdata);

    /**
     * Copy ALL the information from another object.
     * @param rdata Pointer to the object from where the information must be copied.
     */
    void copy(ReaderProxyData* rdata);

    //! get idl crc16
    RTPS_DllAPI std::string getIdlCrc16() const { return m_crc16Idl; }

    //! set idl md5
    RTPS_DllAPI void setIdlCrc16(std::string crc16_input) { m_crc16Idl = std::move(crc16_input); }

    /*locator是否已经过滤过，假如收包已经过滤过，后续无需再处理*/
    void is_filtered(vbs::RemoteEndpointInfo::LocatorType type, bool filter);
    bool is_filtered(vbs::RemoteEndpointInfo::LocatorType type) const;

    /*是否支持请求式，MVBS发现报文需要支持请求式*/
    void is_request_enable(bool enable);
    bool is_request_enable() const;

    bool type_plain() const { return m_type_plain; }
    void type_plain(bool plain) { m_type_plain = plain; }

    void set_host_id(uint16_t host_id) { m_hostId = host_id; }
    uint16_t get_host_id() const { return m_hostId; }

    void set_pid(uint32_t pid) { m_pid = pid; }
    int32_t get_pid() const { return m_pid; }

 private:
    //! GUID
    GUID_t m_guid;
    //! Holds locator information
    RemoteLocatorList remote_locators_;
    //! GUID_t of the Reader converted to InstanceHandle_t
    InstanceHandle_t m_key;
    //! GUID_t of the participant converted to InstanceHandle
    InstanceHandle_t m_RTPSParticipantKey;
    //! Type name
    string_255 m_typeName;
    //! Topic name
    string_255 m_topicName;
    //! User defined ID
    uint16_t m_userDefinedId;
    //! Field to indicate if the Reader is Alive.
    bool m_isAlive;
    //! Topic kind
    TopicKind_t m_topicKind;
    //!
    ParameterPropertyList_t m_properties;
    //! IDL Crc16
    std::string m_crc16Idl = "";

    //!Information on the content filter applied by the reader.
    vbsutil::xmlparser::ContentFilterProperty content_filter_;
    // 判断是否已经过滤locator
    bool is_filtered_[2] = {false};

    // 判断是否支持请求式, MVBS发现报文支持请求式
    bool is_request_enable_ = false;

    bool m_type_plain = false;

    //! Host ID
    uint16_t m_hostId = 0;

    //! Process ID
    int32_t m_pid = 0;
};

}  // namespace rtps
}  // namespace ertps
} /* namespace evbs */

#endif  // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
#endif  // INCLUDE_EDDS_RTPS_BUILTIN_DATA_READERPROXYDATA_H_
